﻿// Decompiled with JetBrains decompiler
// Type: MCM.LightInject.ServiceContainer
// Assembly: MCMv5, Version=5.10.2.0, Culture=neutral, PublicKeyToken=null
// MVID: 7AB326B9-B2B4-41C2-9177-68E944071101
// Assembly location: D:\steam\steamapps\workshop\content\261550\2859238197\bin\Win64_Shipping_Client\MCMv5.dll

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Threading;

#nullable disable
namespace MCM.LightInject
{
  [ExcludeFromCodeCoverage]
  internal class ServiceContainer : IServiceContainer, IServiceRegistry, IServiceFactory, IDisposable
  {
    private const string UnresolvedDependencyError = "Unresolved dependency {0}";
    private static readonly MethodInfo OpenGenericTrackInstanceMethod = typeof (ServiceContainer).GetTypeInfo().GetDeclaredMethod("TrackInstance");
    private readonly Action<LogEntry> log;
    private readonly Func<Type, Type[], IMethodSkeleton> methodSkeletonFactory;
    private readonly ServiceContainer.ServiceRegistry<Action<IEmitter>> emitters = new ServiceContainer.ServiceRegistry<Action<IEmitter>>();
    private readonly ServiceContainer.ServiceRegistry<Delegate> constructorDependencyFactories = new ServiceContainer.ServiceRegistry<Delegate>();
    private readonly ServiceContainer.ServiceRegistry<Delegate> propertyDependencyFactories = new ServiceContainer.ServiceRegistry<Delegate>();
    private readonly ServiceContainer.ServiceRegistry<ServiceRegistration> availableServices = new ServiceContainer.ServiceRegistry<ServiceRegistration>();
    private readonly object lockObject = new object();
    private readonly ContainerOptions options;
    private readonly ServiceContainer.Storage<object> constants = new ServiceContainer.Storage<object>();
    private readonly ServiceContainer.Storage<ILifetime> disposableLifeTimes = new ServiceContainer.Storage<ILifetime>();
    private readonly ServiceContainer.Storage<DecoratorRegistration> decorators = new ServiceContainer.Storage<DecoratorRegistration>();
    private readonly ServiceContainer.Storage<ServiceContainer.ServiceOverride> overrides = new ServiceContainer.Storage<ServiceContainer.ServiceOverride>();
    private readonly ServiceContainer.Storage<ServiceContainer.FactoryRule> factoryRules = new ServiceContainer.Storage<ServiceContainer.FactoryRule>();
    private readonly ServiceContainer.Storage<ServiceContainer.Initializer> initializers = new ServiceContainer.Storage<ServiceContainer.Initializer>();
    private readonly Stack<Action<IEmitter>> dependencyStack = new Stack<Action<IEmitter>>();
    private readonly Lazy<IConstructionInfoProvider> constructionInfoProvider;
    private readonly List<IDisposable> disposableObjects = new List<IDisposable>();
    private readonly LazyConcurrentDictionary<ServiceRegistration, int> servicesToDelegatesIndex = new LazyConcurrentDictionary<ServiceRegistration, int>();
    private ImmutableHashTable<Type, GetInstanceDelegate> delegates = ImmutableHashTable<Type, GetInstanceDelegate>.Empty;
    private ImmutableHashTable<(Type, string), GetInstanceDelegate> namedDelegates = ImmutableHashTable<(Type, string), GetInstanceDelegate>.Empty;
    private ImmutableHashTree<Type, Func<object[], Scope, object, object>> propertyInjectionDelegates = ImmutableHashTree<Type, Func<object[], Scope, object, object>>.Empty;
    private bool isLocked;
    private Type defaultLifetimeType;

    public ServiceContainer()
      : this(ContainerOptions.Default)
    {
    }

    public ServiceContainer(Action<ContainerOptions> configureOptions)
    {
      this.options = new ContainerOptions();
      configureOptions(this.options);
      this.log = this.options.LogFactory(typeof (ServiceContainer));
      CachedTypeExtractor concreteTypeExtractor = new CachedTypeExtractor((ITypeExtractor) new ConcreteTypeExtractor());
      this.CompositionRootTypeExtractor = (ITypeExtractor) new CachedTypeExtractor((ITypeExtractor) new MCM.LightInject.CompositionRootTypeExtractor((ICompositionRootAttributeExtractor) new CompositionRootAttributeExtractor()));
      this.CompositionRootExecutor = (ICompositionRootExecutor) new MCM.LightInject.CompositionRootExecutor((IServiceRegistry) this, (Func<Type, ICompositionRoot>) (type => (ICompositionRoot) Activator.CreateInstance(type)));
      this.ServiceNameProvider = (IServiceNameProvider) new MCM.LightInject.ServiceNameProvider();
      this.PropertyDependencySelector = this.options.EnablePropertyInjection ? (IPropertyDependencySelector) new MCM.LightInject.PropertyDependencySelector((IPropertySelector) new PropertySelector()) : (IPropertyDependencySelector) new ServiceContainer.PropertyDependencyDisabler();
      this.GenericArgumentMapper = (IGenericArgumentMapper) new MCM.LightInject.GenericArgumentMapper();
      this.AssemblyScanner = (IAssemblyScanner) new MCM.LightInject.AssemblyScanner((ITypeExtractor) concreteTypeExtractor, this.CompositionRootTypeExtractor, this.CompositionRootExecutor, this.GenericArgumentMapper);
      this.ConstructorDependencySelector = (IConstructorDependencySelector) new MCM.LightInject.ConstructorDependencySelector();
      this.ConstructorSelector = (IConstructorSelector) new MostResolvableConstructorSelector(new Func<Type, string, bool>(this.CanGetInstance), this.options.EnableOptionalArguments);
      this.constructionInfoProvider = new Lazy<IConstructionInfoProvider>(new Func<IConstructionInfoProvider>(this.CreateConstructionInfoProvider));
      this.methodSkeletonFactory = (Func<Type, Type[], IMethodSkeleton>) ((returnType, parameterTypes) => (IMethodSkeleton) new ServiceContainer.DynamicMethodSkeleton(returnType, parameterTypes));
      this.ScopeManagerProvider = (IScopeManagerProvider) new PerLogicalCallContextScopeManagerProvider();
      this.AssemblyLoader = (IAssemblyLoader) new MCM.LightInject.AssemblyLoader();
    }

    public ServiceContainer(ContainerOptions options)
      : this((Action<ContainerOptions>) (o =>
      {
        o.LogFactory = options.LogFactory;
        o.DefaultServiceSelector = options.DefaultServiceSelector;
        o.EnableCurrentScope = options.EnableCurrentScope;
        o.EnablePropertyInjection = options.EnablePropertyInjection;
        o.EnableVariance = options.EnableVariance;
        o.VarianceFilter = options.VarianceFilter;
        o.EnableOptionalArguments = options.EnableOptionalArguments;
        o.OptimizeForLargeObjectGraphs = options.OptimizeForLargeObjectGraphs;
      }))
    {
    }

    private ServiceContainer(
      ContainerOptions options,
      ServiceContainer.ServiceRegistry<Delegate> constructorDependencyFactories,
      ServiceContainer.ServiceRegistry<Delegate> propertyDependencyFactories,
      ServiceContainer.ServiceRegistry<ServiceRegistration> availableServices,
      ServiceContainer.Storage<DecoratorRegistration> decorators,
      ServiceContainer.Storage<ServiceContainer.ServiceOverride> overrides,
      ServiceContainer.Storage<ServiceContainer.FactoryRule> factoryRules,
      ServiceContainer.Storage<ServiceContainer.Initializer> initializers,
      Lazy<IConstructionInfoProvider> constructionInfoProvider,
      Func<Type, Type[], IMethodSkeleton> methodSkeletonFactory,
      Action<LogEntry> log,
      ICompositionRootExecutor compositionRootExecutor,
      IServiceNameProvider serviceNameProvider,
      IPropertyDependencySelector propertyDependencySelector,
      IGenericArgumentMapper genericArgumentMapper,
      IAssemblyScanner assemblyScanner,
      IConstructorDependencySelector constructorDependencySelector,
      IConstructorSelector constructorSelector,
      IAssemblyLoader assemblyLoader,
      IScopeManagerProvider scopeManagerProvider)
    {
      this.options = options;
      this.constructorDependencyFactories = constructorDependencyFactories;
      this.propertyDependencyFactories = propertyDependencyFactories;
      this.availableServices = availableServices;
      this.decorators = decorators;
      this.overrides = overrides;
      this.factoryRules = factoryRules;
      this.initializers = initializers;
      this.constructionInfoProvider = constructionInfoProvider;
      this.methodSkeletonFactory = methodSkeletonFactory;
      this.log = log;
      this.CompositionRootExecutor = compositionRootExecutor;
      this.ServiceNameProvider = serviceNameProvider;
      this.PropertyDependencySelector = propertyDependencySelector;
      this.GenericArgumentMapper = genericArgumentMapper;
      this.AssemblyScanner = assemblyScanner;
      this.ConstructorDependencySelector = constructorDependencySelector;
      this.ConstructorSelector = constructorSelector;
      this.ScopeManagerProvider = scopeManagerProvider;
      this.AssemblyLoader = assemblyLoader;
      foreach (ServiceRegistration availableService in this.AvailableServices)
        this.Register(availableService);
    }

    public IScopeManagerProvider ScopeManagerProvider { get; set; }

    public IPropertyDependencySelector PropertyDependencySelector { get; set; }

    public ITypeExtractor CompositionRootTypeExtractor { get; set; }

    public IServiceNameProvider ServiceNameProvider { get; set; }

    public ICompositionRootExecutor CompositionRootExecutor { get; set; }

    public IConstructorDependencySelector ConstructorDependencySelector { get; set; }

    public IConstructorSelector ConstructorSelector { get; set; }

    public IGenericArgumentMapper GenericArgumentMapper { get; set; }

    public IAssemblyScanner AssemblyScanner { get; set; }

    public IAssemblyLoader AssemblyLoader { get; set; }

    public IEnumerable<ServiceRegistration> AvailableServices
    {
      get
      {
        return this.availableServices.Values.SelectMany<ThreadSafeDictionary<string, ServiceRegistration>, ServiceRegistration>((Func<ThreadSafeDictionary<string, ServiceRegistration>, IEnumerable<ServiceRegistration>>) (t => (IEnumerable<ServiceRegistration>) t.Values));
      }
    }

    private ILifetime DefaultLifetime
    {
      get
      {
        return this.defaultLifetimeType != (Type) null ? (ILifetime) Activator.CreateInstance(this.defaultLifetimeType) : (ILifetime) (object) null;
      }
    }

    public bool CanGetInstance(Type serviceType, string serviceName)
    {
      return serviceType.IsFuncRepresentingService() || serviceType.IsFuncRepresentingNamedService() || serviceType.IsFuncWithParameters() || serviceType.IsLazy() ? this.GetEmitMethod(((IEnumerable<Type>) serviceType.GenericTypeArguments).Last<Type>(), serviceName) != null || this.availableServices.ContainsKey(serviceType) : this.GetEmitMethod(serviceType, serviceName) != null;
    }

    public Scope BeginScope()
    {
      return this.options.EnableCurrentScope ? this.ScopeManagerProvider.GetScopeManager((IServiceFactory) this).BeginScope() : new Scope(this);
    }

    public object InjectProperties(object instance)
    {
      Type type = instance.GetType();
      Func<object[], Scope, object, object> func = this.propertyInjectionDelegates.Search<Type, Func<object[], Scope, object, object>>(type);
      if (func == null)
      {
        func = this.CreatePropertyInjectionDelegate(type);
        this.propertyInjectionDelegates = this.propertyInjectionDelegates.Add<Type, Func<object[], Scope, object, object>>(type, func);
      }
      return func(this.constants.Items, (Scope) null, instance);
    }

    public IServiceRegistry Register<TService>(
      Func<IServiceFactory, TService> factory,
      string serviceName,
      ILifetime lifetime)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, lifetime, serviceName);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterFallback(
      Func<Type, string, bool> predicate,
      Func<ServiceRequest, object> factory)
    {
      return this.RegisterFallback(predicate, factory, this.DefaultLifetime);
    }

    public IServiceRegistry RegisterFallback(
      Func<Type, string, bool> predicate,
      Func<ServiceRequest, object> factory,
      ILifetime lifetime)
    {
      this.factoryRules.Add(new ServiceContainer.FactoryRule()
      {
        CanCreateInstance = predicate,
        Factory = factory,
        LifeTime = lifetime
      });
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register(ServiceRegistration serviceRegistration)
    {
      ThreadSafeDictionary<string, ServiceRegistration> availableServices = this.GetAvailableServices(serviceRegistration.ServiceType);
      ServiceRegistration sr = serviceRegistration;
      availableServices.AddOrUpdate(serviceRegistration.ServiceName, (Func<string, ServiceRegistration>) (s => this.AddServiceRegistration(sr)), (Func<string, ServiceRegistration, ServiceRegistration>) ((k, existing) => this.UpdateServiceRegistration(existing, sr)));
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterAssembly(Assembly assembly)
    {
      if (this.CompositionRootTypeExtractor.Execute(assembly).Length == 0)
        this.RegisterAssembly(assembly, (Func<Type, Type, bool>) ((serviceType, implementingType) => true));
      else
        this.AssemblyScanner.Scan(assembly, (IServiceRegistry) this);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterAssembly(
      Assembly assembly,
      Func<Type, Type, bool> shouldRegister)
    {
      return this.RegisterAssembly(assembly, (Func<ILifetime>) (() => this.DefaultLifetime), shouldRegister);
    }

    public IServiceRegistry RegisterAssembly(Assembly assembly, Func<ILifetime> lifetimeFactory)
    {
      return this.RegisterAssembly(assembly, lifetimeFactory, (Func<Type, Type, bool>) ((serviceType, implementingType) => true));
    }

    public IServiceRegistry RegisterAssembly(
      Assembly assembly,
      Func<ILifetime> lifetimeFactory,
      Func<Type, Type, bool> shouldRegister)
    {
      return this.RegisterAssembly(assembly, lifetimeFactory, shouldRegister, new Func<Type, Type, string>(this.ServiceNameProvider.GetServiceName));
    }

    public IServiceRegistry RegisterAssembly(
      Assembly assembly,
      Func<ILifetime> lifetimeFactory,
      Func<Type, Type, bool> shouldRegister,
      Func<Type, Type, string> serviceNameProvider)
    {
      this.AssemblyScanner.Scan(assembly, (IServiceRegistry) this, lifetimeFactory, shouldRegister, serviceNameProvider);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterFrom<TCompositionRoot>() where TCompositionRoot : ICompositionRoot, new()
    {
      this.CompositionRootExecutor.Execute(typeof (TCompositionRoot));
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterFrom<TCompositionRoot>(TCompositionRoot compositionRoot) where TCompositionRoot : ICompositionRoot
    {
      this.CompositionRootExecutor.Execute<TCompositionRoot>(compositionRoot);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterConstructorDependency<TDependency>(
      Func<IServiceFactory, ParameterInfo, TDependency> factory)
    {
      if (this.isLocked)
        this.log.Warning(string.Format("Attempt to register a constructor dependency {0} after the first call to GetInstance.", (object) typeof (TDependency)) + string.Format("This might lead to incorrect behavior if a service with a {0} dependency has already been resolved", (object) typeof (TDependency)));
      this.GetConstructorDependencyFactories(typeof (TDependency)).AddOrUpdate(string.Empty, (Func<string, Delegate>) (s => (Delegate) factory), (Func<string, Delegate, Delegate>) ((s, e) => !this.isLocked ? (Delegate) factory : e));
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterConstructorDependency<TDependency>(
      Func<IServiceFactory, ParameterInfo, object[], TDependency> factory)
    {
      if (this.isLocked)
        this.log.Warning(string.Format("Attempt to register a constructor dependency {0} after the first call to GetInstance.", (object) typeof (TDependency)) + string.Format("This might lead to incorrect behavior if a service with a {0} dependency has already been resolved", (object) typeof (TDependency)));
      this.GetConstructorDependencyFactories(typeof (TDependency)).AddOrUpdate(string.Empty, (Func<string, Delegate>) (s => (Delegate) factory), (Func<string, Delegate, Delegate>) ((s, e) => !this.isLocked ? (Delegate) factory : e));
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterPropertyDependency<TDependency>(
      Func<IServiceFactory, PropertyInfo, TDependency> factory)
    {
      if (this.isLocked)
        this.log.Warning(string.Format("Attempt to register a property dependency {0} after the first call to GetInstance.", (object) typeof (TDependency)) + string.Format("This might lead to incorrect behavior if a service with a {0} dependency has already been resolved", (object) typeof (TDependency)));
      this.GetPropertyDependencyFactories(typeof (TDependency)).AddOrUpdate(string.Empty, (Func<string, Delegate>) (s => (Delegate) factory), (Func<string, Delegate, Delegate>) ((s, e) => !this.isLocked ? (Delegate) factory : e));
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterAssembly(string searchPattern)
    {
      foreach (Assembly assembly in this.AssemblyLoader.Load(searchPattern))
        this.RegisterAssembly(assembly);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Decorate(
      Type serviceType,
      Type decoratorType,
      Func<ServiceRegistration, bool> predicate)
    {
      DecoratorRegistration decoratorRegistration = new DecoratorRegistration();
      decoratorRegistration.ServiceType = serviceType;
      decoratorRegistration.ImplementingType = decoratorType;
      decoratorRegistration.CanDecorate = predicate;
      this.Decorate(decoratorRegistration);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Decorate(Type serviceType, Type decoratorType)
    {
      this.Decorate(serviceType, decoratorType, (Func<ServiceRegistration, bool>) (si => true));
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Decorate<TService, TDecorator>() where TDecorator : TService
    {
      this.Decorate(typeof (TService), typeof (TDecorator));
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Decorate<TService>(Func<IServiceFactory, TService, TService> factory)
    {
      DecoratorRegistration decoratorRegistration = new DecoratorRegistration();
      decoratorRegistration.FactoryExpression = (Delegate) factory;
      decoratorRegistration.ServiceType = typeof (TService);
      decoratorRegistration.CanDecorate = (Func<ServiceRegistration, bool>) (si => true);
      this.Decorate(decoratorRegistration);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Decorate(DecoratorRegistration decoratorRegistration)
    {
      int num = this.decorators.Add(decoratorRegistration);
      decoratorRegistration.Index = num;
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Override(
      Func<ServiceRegistration, bool> serviceSelector,
      Func<IServiceFactory, ServiceRegistration, ServiceRegistration> serviceRegistrationFactory)
    {
      this.overrides.Add(new ServiceContainer.ServiceOverride(serviceSelector, serviceRegistrationFactory));
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Initialize(
      Func<ServiceRegistration, bool> predicate,
      Action<IServiceFactory, object> processor)
    {
      this.initializers.Add(new ServiceContainer.Initializer()
      {
        Predicate = predicate,
        Initialize = processor
      });
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register(Type serviceType, Type implementingType, ILifetime lifetime)
    {
      this.Register(serviceType, implementingType, string.Empty, lifetime);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register(
      Type serviceType,
      Type implementingType,
      string serviceName,
      ILifetime lifetime)
    {
      this.RegisterService(serviceType, implementingType, lifetime, serviceName);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<TService, TImplementation>() where TImplementation : TService
    {
      this.Register(typeof (TService), typeof (TImplementation));
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<TService, TImplementation>(ILifetime lifetime) where TImplementation : TService
    {
      this.Register(typeof (TService), typeof (TImplementation), lifetime);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<TService, TImplementation>(string serviceName) where TImplementation : TService
    {
      this.Register<TService, TImplementation>(serviceName, (ILifetime) null);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<TService, TImplementation>(
      string serviceName,
      ILifetime lifetime)
      where TImplementation : TService
    {
      this.Register(typeof (TService), typeof (TImplementation), serviceName, lifetime);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<TService>(
      Func<IServiceFactory, TService> factory,
      ILifetime lifetime)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, lifetime, string.Empty);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<TService>(
      Func<IServiceFactory, TService> factory,
      string serviceName)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, (ILifetime) null, serviceName);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<TService>()
    {
      this.Register<TService, TService>();
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register(Type serviceType)
    {
      this.Register(serviceType, serviceType);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register(Type serviceType, ILifetime lifetime)
    {
      this.Register(serviceType, serviceType, lifetime);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<TService>(ILifetime lifetime)
    {
      this.Register<TService, TService>(lifetime);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterInstance<TService>(TService instance, string serviceName)
    {
      this.RegisterInstance(typeof (TService), (object) instance, serviceName);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterInstance<TService>(TService instance)
    {
      this.RegisterInstance(typeof (TService), (object) instance);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterInstance(Type serviceType, object instance)
    {
      this.RegisterInstance(serviceType, instance, string.Empty);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterInstance(Type serviceType, object instance, string serviceName)
    {
      Ensure.IsNotNull<object>(instance, nameof (instance));
      Ensure.IsNotNull<Type>(serviceType, "type");
      Ensure.IsNotNull<string>(serviceName, nameof (serviceName));
      this.RegisterValue(serviceType, instance, serviceName);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<TService>(Func<IServiceFactory, TService> factory)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, (ILifetime) null, string.Empty);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<T, TService>(Func<IServiceFactory, T, TService> factory)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, (ILifetime) null, string.Empty);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<T, TService>(
      Func<IServiceFactory, T, TService> factory,
      string serviceName)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, (ILifetime) null, serviceName);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<T1, T2, TService>(
      Func<IServiceFactory, T1, T2, TService> factory)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, (ILifetime) null, string.Empty);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<T1, T2, TService>(
      Func<IServiceFactory, T1, T2, TService> factory,
      string serviceName)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, (ILifetime) null, serviceName);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<T1, T2, T3, TService>(
      Func<IServiceFactory, T1, T2, T3, TService> factory)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, (ILifetime) null, string.Empty);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<T1, T2, T3, TService>(
      Func<IServiceFactory, T1, T2, T3, TService> factory,
      string serviceName)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, (ILifetime) null, serviceName);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<T1, T2, T3, T4, TService>(
      Func<IServiceFactory, T1, T2, T3, T4, TService> factory)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, (ILifetime) null, string.Empty);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register<T1, T2, T3, T4, TService>(
      Func<IServiceFactory, T1, T2, T3, T4, TService> factory,
      string serviceName)
    {
      this.RegisterServiceFromLambdaExpression<TService>((Delegate) factory, (ILifetime) null, serviceName);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register(Type serviceType, Type implementingType, string serviceName)
    {
      this.RegisterService(serviceType, implementingType, (ILifetime) null, serviceName);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry Register(Type serviceType, Type implementingType)
    {
      this.RegisterService(serviceType, implementingType, (ILifetime) null, string.Empty);
      return (IServiceRegistry) this;
    }

    public IServiceRegistry RegisterOrdered(
      Type serviceType,
      Type[] implementingTypes,
      Func<Type, ILifetime> lifeTimeFactory)
    {
      return this.RegisterOrdered(serviceType, implementingTypes, lifeTimeFactory, (Func<int, string>) (i => i.ToString().PadLeft(3, '0')));
    }

    public IServiceRegistry RegisterOrdered(
      Type serviceType,
      Type[] implementingTypes,
      Func<Type, ILifetime> lifeTimeFactory,
      Func<int, string> serviceNameFormatter)
    {
      int count = this.GetAvailableServices(serviceType).Count;
      foreach (Type implementingType in implementingTypes)
      {
        ++count;
        this.Register(serviceType, implementingType, serviceNameFormatter(count), lifeTimeFactory(implementingType));
      }
      return (IServiceRegistry) this;
    }

    public void Compile(Func<ServiceRegistration, bool> predicate)
    {
      foreach (ServiceRegistration serviceRegistration in this.AvailableServices.Where<ServiceRegistration>(predicate).ToArray<ServiceRegistration>())
      {
        if (serviceRegistration.ServiceType.GetTypeInfo().IsGenericTypeDefinition)
          this.log.Warning("Unable to precompile open generic type '" + GetPrettyName(serviceRegistration.ServiceType) + "'");
        else if (string.IsNullOrWhiteSpace(serviceRegistration.ServiceName))
          this.CreateDefaultDelegate(serviceRegistration.ServiceType, true);
        else
          this.CreateNamedDelegate((serviceRegistration.ServiceType, serviceRegistration.ServiceName), true);
      }

      static string GetPrettyName(Type type)
      {
        return type.GetTypeInfo().IsGenericType ? type.FullName.Substring(0, type.FullName.LastIndexOf("`", StringComparison.OrdinalIgnoreCase)) + "<" + string.Join(", ", ((IEnumerable<Type>) type.GetTypeInfo().GenericTypeParameters).Select<Type, string>(new Func<Type, string>(GetPrettyName))) + ">" : type.Name;
      }
    }

    public void Compile() => this.Compile((Func<ServiceRegistration, bool>) (sr => true));

    public void Compile<TService>(string serviceName = null)
    {
      if (string.IsNullOrWhiteSpace(serviceName))
        this.CreateDefaultDelegate(typeof (TService), true);
      else
        this.CreateNamedDelegate((typeof (TService), serviceName), true);
    }

    public object GetInstance(Type serviceType)
    {
      return (this.delegates.Search(serviceType) ?? this.CreateDefaultDelegate(serviceType, true))(this.constants.Items, (Scope) null);
    }

    public object GetInstance(Type serviceType, object[] arguments)
    {
      return (this.delegates.Search(serviceType) ?? this.CreateDefaultDelegate(serviceType, true))(((IEnumerable<object>) this.constants.Items).Concat<object>((IEnumerable<object>) new object[1]
      {
        (object) arguments
      }).ToArray<object>(), (Scope) null);
    }

    public object GetInstance(Type serviceType, string serviceName, object[] arguments)
    {
      (Type, string) key = (serviceType, serviceName);
      return (this.namedDelegates.Search<(Type, string), GetInstanceDelegate>(key) ?? this.CreateNamedDelegate(key, true))(((IEnumerable<object>) this.constants.Items).Concat<object>((IEnumerable<object>) new object[1]
      {
        (object) arguments
      }).ToArray<object>(), (Scope) null);
    }

    public object TryGetInstance(Type serviceType)
    {
      return (this.delegates.Search(serviceType) ?? this.CreateDefaultDelegate(serviceType, false))(this.constants.Items, (Scope) null);
    }

    public object TryGetInstance(Type serviceType, string serviceName)
    {
      (Type, string) key = (serviceType, serviceName);
      return (this.namedDelegates.Search<(Type, string), GetInstanceDelegate>(key) ?? this.CreateNamedDelegate(key, false))(this.constants.Items, (Scope) null);
    }

    public object GetInstance(Type serviceType, string serviceName)
    {
      (Type, string) key = (serviceType, serviceName);
      return (this.namedDelegates.Search<(Type, string), GetInstanceDelegate>(key) ?? this.CreateNamedDelegate(key, true))(this.constants.Items, (Scope) null);
    }

    public IEnumerable<object> GetAllInstances(Type serviceType)
    {
      return (IEnumerable<object>) this.GetInstance(serviceType.GetEnumerableType());
    }

    public object Create(Type serviceType)
    {
      this.Register(serviceType);
      return this.GetInstance(serviceType);
    }

    public IServiceRegistry SetDefaultLifetime<T>() where T : ILifetime, new()
    {
      this.defaultLifetimeType = typeof (T);
      return (IServiceRegistry) this;
    }

    public void Dispose()
    {
      foreach (IDisposable disposable in ((IEnumerable<ILifetime>) this.disposableLifeTimes.Items).Where<ILifetime>((Func<ILifetime, bool>) (lt => lt is IDisposable)).Cast<IDisposable>().Reverse<IDisposable>())
        disposable.Dispose();
      foreach (IDisposable disposable in this.disposableObjects.AsEnumerable<IDisposable>().Reverse<IDisposable>())
        disposable.Dispose();
    }

    public ServiceContainer Clone()
    {
      return new ServiceContainer(this.options, this.constructorDependencyFactories, this.propertyDependencyFactories, this.availableServices, this.decorators, this.overrides, this.factoryRules, this.initializers, this.constructionInfoProvider, this.methodSkeletonFactory, this.log, this.CompositionRootExecutor, this.ServiceNameProvider, this.PropertyDependencySelector, this.GenericArgumentMapper, this.AssemblyScanner, this.ConstructorDependencySelector, this.ConstructorSelector, this.AssemblyLoader, this.ScopeManagerProvider);
    }

    internal static TService TrackInstance<TService>(TService instance, ServiceContainer container)
    {
      if (instance is IDisposable disposable)
        container.disposableObjects.Add(disposable);
      return instance;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    internal object GetInstance(Type serviceType, Scope scope)
    {
      return (this.delegates.Search(serviceType) ?? this.CreateDefaultDelegate(serviceType, true))(this.constants.Items, scope);
    }

    internal object GetInstance(Type serviceType, Scope scope, string serviceName)
    {
      (Type, string) key = (serviceType, serviceName);
      return (this.namedDelegates.Search<(Type, string), GetInstanceDelegate>(key) ?? this.CreateNamedDelegate(key, true))(this.constants.Items, scope);
    }

    internal IEnumerable<object> GetAllInstances(Type serviceType, Scope scope)
    {
      return (IEnumerable<object>) this.GetInstance(serviceType.GetEnumerableType(), scope);
    }

    internal object GetInstance(Type serviceType, object[] arguments, Scope scope)
    {
      return (this.delegates.Search(serviceType) ?? this.CreateDefaultDelegate(serviceType, true))(((IEnumerable<object>) this.constants.Items).Concat<object>((IEnumerable<object>) new object[1]
      {
        (object) arguments
      }).ToArray<object>(), scope);
    }

    internal object GetInstance(
      Type serviceType,
      string serviceName,
      object[] arguments,
      Scope scope)
    {
      (Type, string) key = (serviceType, serviceName);
      return (this.namedDelegates.Search<(Type, string), GetInstanceDelegate>(key) ?? this.CreateNamedDelegate(key, true))(((IEnumerable<object>) this.constants.Items).Concat<object>((IEnumerable<object>) new object[1]
      {
        (object) arguments
      }).ToArray<object>(), scope);
    }

    internal object TryGetInstance(Type serviceType, Scope scope)
    {
      return (this.delegates.Search(serviceType) ?? this.CreateDefaultDelegate(serviceType, false))(this.constants.Items, scope);
    }

    internal object TryGetInstance(Type serviceType, string serviceName, Scope scope)
    {
      (Type, string) key = (serviceType, serviceName);
      return (this.namedDelegates.Search<(Type, string), GetInstanceDelegate>(key) ?? this.CreateNamedDelegate(key, false))(this.constants.Items, scope);
    }

    internal object Create(Type serviceType, Scope scope)
    {
      this.Register(serviceType);
      return this.GetInstance(serviceType, scope);
    }

    private static void EmitEnumerable(
      IList<Action<IEmitter>> serviceEmitters,
      Type elementType,
      IEmitter emitter)
    {
      ServiceContainer.EmitNewArray(serviceEmitters, elementType, emitter);
    }

    private static void EmitNewArray(
      IList<Action<IEmitter>> emitMethods,
      Type elementType,
      IEmitter emitter)
    {
      LocalBuilder localBuilder = emitter.DeclareLocal(elementType.MakeArrayType());
      emitter.Push(emitMethods.Count);
      emitter.PushNewArray(elementType);
      emitter.Store(localBuilder);
      for (int index = 0; index < emitMethods.Count; ++index)
      {
        emitter.Push(localBuilder);
        emitter.Push(index);
        emitMethods[index](emitter);
        emitter.UnboxOrCast(elementType);
        emitter.Emit(OpCodes.Stelem, elementType);
      }
      emitter.Push(localBuilder);
    }

    private static ILifetime CloneLifeTime(ILifetime lifetime)
    {
      return lifetime is ICloneableLifeTime cloneableLifeTime ? cloneableLifeTime.Clone() : (lifetime == null ? (ILifetime) null : (ILifetime) Activator.CreateInstance(lifetime.GetType()));
    }

    private static ConstructorDependency GetConstructorDependencyThatRepresentsDecoratorTarget(
      DecoratorRegistration decoratorRegistration,
      ConstructionInfo constructionInfo)
    {
      return constructionInfo.ConstructorDependencies.FirstOrDefault<ConstructorDependency>((Func<ConstructorDependency, bool>) (cd =>
      {
        if (cd.ServiceType == decoratorRegistration.ServiceType)
          return true;
        return cd.ServiceType.IsLazy() && cd.ServiceType.GetTypeInfo().GenericTypeArguments[0] == decoratorRegistration.ServiceType;
      }));
    }

    private static void PushRuntimeArguments(IEmitter emitter)
    {
      MethodInfo declaredMethod = typeof (RuntimeArgumentsLoader).GetTypeInfo().GetDeclaredMethod("Load");
      emitter.Emit(OpCodes.Ldarg_0);
      emitter.Emit(OpCodes.Call, declaredMethod);
    }

    private DecoratorRegistration CreateClosedGenericDecoratorRegistration(
      ServiceRegistration serviceRegistration,
      DecoratorRegistration openGenericDecorator)
    {
      Type implementingType = openGenericDecorator.ImplementingType;
      Type serviceType = serviceRegistration.ServiceType;
      Type[] genericTypeArguments = serviceType.GenericTypeArguments;
      Type closedGenericDecoratorType;
      if (!this.TryCreateClosedGenericDecoratorType(serviceType, implementingType, out closedGenericDecoratorType))
      {
        this.log.Info("Skipping decorator [" + implementingType.FullName + "] since it is incompatible with the service type [" + serviceType.FullName + "]");
        return (DecoratorRegistration) null;
      }
      DecoratorRegistration decoratorRegistration = new DecoratorRegistration();
      decoratorRegistration.ServiceType = serviceRegistration.ServiceType;
      decoratorRegistration.ImplementingType = closedGenericDecoratorType;
      decoratorRegistration.CanDecorate = openGenericDecorator.CanDecorate;
      decoratorRegistration.Index = openGenericDecorator.Index;
      return decoratorRegistration;
    }

    private bool TryCreateClosedGenericDecoratorType(
      Type serviceType,
      Type implementingType,
      out Type closedGenericDecoratorType)
    {
      closedGenericDecoratorType = (Type) null;
      GenericMappingResult genericMappingResult = this.GenericArgumentMapper.Map(serviceType, implementingType);
      if (!genericMappingResult.IsValid)
        return false;
      closedGenericDecoratorType = TypeHelper.TryMakeGenericType(implementingType, genericMappingResult.GetMappedArguments());
      return !(closedGenericDecoratorType == (Type) null) && serviceType.GetTypeInfo().IsAssignableFrom(closedGenericDecoratorType.GetTypeInfo());
    }

    private Func<object[], Scope, object, object> CreatePropertyInjectionDelegate(Type concreteType)
    {
      lock (this.lockObject)
      {
        IMethodSkeleton methodSkeleton = this.methodSkeletonFactory(typeof (object), new Type[3]
        {
          typeof (object[]),
          typeof (Scope),
          typeof (object)
        });
        ConstructionInfo constructionInfo = new ConstructionInfo();
        constructionInfo.PropertyDependencies.AddRange(this.PropertyDependencySelector.Execute(concreteType));
        constructionInfo.ImplementingType = concreteType;
        IEmitter emitter = methodSkeleton.GetEmitter();
        emitter.PushArgument(2);
        emitter.Cast(concreteType);
        try
        {
          this.EmitPropertyDependencies(constructionInfo, emitter);
        }
        catch (Exception ex)
        {
          this.dependencyStack.Clear();
          throw;
        }
        emitter.Return();
        this.isLocked = true;
        return (Func<object[], Scope, object, object>) methodSkeleton.CreateDelegate(typeof (Func<object[], Scope, object, object>));
      }
    }

    private ConstructionInfoProvider CreateConstructionInfoProvider()
    {
      return new ConstructionInfoProvider((IConstructionInfoBuilder) this.CreateTypeConstructionInfoBuilder());
    }

    private TypeConstructionInfoBuilder CreateTypeConstructionInfoBuilder()
    {
      return new TypeConstructionInfoBuilder(this.ConstructorSelector, this.ConstructorDependencySelector, this.PropertyDependencySelector, new Func<Type, string, Delegate>(this.GetConstructorDependencyDelegate), new Func<Type, string, Delegate>(this.GetPropertyDependencyExpression));
    }

    private Delegate GetConstructorDependencyDelegate(Type type, string serviceName)
    {
      Delegate dependencyDelegate;
      this.GetConstructorDependencyFactories(type).TryGetValue(serviceName, out dependencyDelegate);
      return dependencyDelegate;
    }

    private Delegate GetPropertyDependencyExpression(Type type, string serviceName)
    {
      Delegate dependencyExpression;
      this.GetPropertyDependencyFactories(type).TryGetValue(serviceName, out dependencyExpression);
      return dependencyExpression;
    }

    private GetInstanceDelegate CreateDynamicMethodDelegate(Action<IEmitter> serviceEmitter)
    {
      IMethodSkeleton methodSkeleton = this.methodSkeletonFactory(typeof (object), new Type[2]
      {
        typeof (object[]),
        typeof (Scope)
      });
      IEmitter emitter = methodSkeleton.GetEmitter();
      serviceEmitter(emitter);
      if (emitter.StackType.GetTypeInfo().IsValueType)
        emitter.Emit(OpCodes.Box, emitter.StackType);
      Instruction instruction = emitter.Instructions.Last<Instruction>();
      if (instruction.Code == OpCodes.Castclass)
        emitter.Instructions.Remove(instruction);
      emitter.Return();
      this.isLocked = true;
      return (GetInstanceDelegate) methodSkeleton.CreateDelegate(typeof (GetInstanceDelegate));
    }

    private Action<IEmitter> GetEmitMethod(Type serviceType, string serviceName)
    {
      Action<IEmitter> emitter = this.GetRegisteredEmitMethod(serviceType, serviceName) ?? this.TryGetFallbackEmitMethod(serviceType, serviceName);
      if (emitter == null)
      {
        this.AssemblyScanner.Scan(serviceType.GetTypeInfo().Assembly, (IServiceRegistry) this);
        emitter = this.GetRegisteredEmitMethod(serviceType, serviceName);
      }
      if (emitter == null)
        emitter = this.TryGetFallbackEmitMethod(serviceType, serviceName);
      return this.CreateEmitMethodWrapper(emitter, serviceType, serviceName);
    }

    private Action<IEmitter> TryGetFallbackEmitMethod(Type serviceType, string serviceName)
    {
      Action<IEmitter> emitMethod = (Action<IEmitter>) null;
      ServiceContainer.FactoryRule rule = ((IEnumerable<ServiceContainer.FactoryRule>) this.factoryRules.Items).FirstOrDefault<ServiceContainer.FactoryRule>((Func<ServiceContainer.FactoryRule, bool>) (r => r.CanCreateInstance(serviceType, serviceName)));
      if (rule != null)
      {
        emitMethod = this.CreateServiceEmitterBasedOnFactoryRule(rule, serviceType, serviceName);
        this.RegisterEmitMethod(serviceType, serviceName, emitMethod);
      }
      return emitMethod;
    }

    private Action<IEmitter> CreateEmitMethodWrapper(
      Action<IEmitter> emitter,
      Type serviceType,
      string serviceName)
    {
      return emitter == null ? (Action<IEmitter>) null : (Action<IEmitter>) (ms =>
      {
        if (this.dependencyStack.Contains(emitter))
          throw new InvalidOperationException(string.Format("Recursive dependency detected: ServiceType:{0}, ServiceName:{1}]", (object) serviceType, (object) serviceName));
        this.dependencyStack.Push(emitter);
        try
        {
          emitter(ms);
        }
        finally
        {
          if (this.dependencyStack.Count > 0)
            this.dependencyStack.Pop();
        }
      });
    }

    private Action<IEmitter> GetRegisteredEmitMethod(Type serviceType, string serviceName)
    {
      ThreadSafeDictionary<string, Action<IEmitter>> emitMethods = this.GetEmitMethods(serviceType);
      if (string.IsNullOrWhiteSpace(serviceName))
        serviceName = emitMethods.Count <= 1 ? string.Empty : this.options.DefaultServiceSelector(emitMethods.Keys.OrderBy<string, string>((Func<string, string>) (k => k)).ToArray<string>());
      Action<IEmitter> action;
      emitMethods.TryGetValue(serviceName, out action);
      return action ?? this.CreateEmitMethodForUnknownService(serviceType, serviceName);
    }

    private ServiceRegistration AddServiceRegistration(ServiceRegistration serviceRegistration)
    {
      Action<IEmitter> emitMethod = this.ResolveEmitMethod(serviceRegistration);
      this.RegisterEmitMethod(serviceRegistration.ServiceType, serviceRegistration.ServiceName, emitMethod);
      return serviceRegistration;
    }

    private void RegisterEmitMethod(
      Type serviceType,
      string serviceName,
      Action<IEmitter> emitMethod)
    {
      this.GetEmitMethods(serviceType).TryAdd(serviceName, emitMethod);
    }

    private ServiceRegistration UpdateServiceRegistration(
      ServiceRegistration existingRegistration,
      ServiceRegistration newRegistration)
    {
      if (this.isLocked)
      {
        this.log.Warning(string.Format("Cannot overwrite existing serviceregistration {0} after the first call to GetInstance.", (object) existingRegistration));
        return existingRegistration;
      }
      Action<IEmitter> action = this.ResolveEmitMethod(newRegistration);
      this.GetEmitMethods(newRegistration.ServiceType)[newRegistration.ServiceName] = action;
      return newRegistration;
    }

    private DecoratorRegistration[] GetDecorators(ServiceRegistration serviceRegistration)
    {
      List<DecoratorRegistration> list = ((IEnumerable<DecoratorRegistration>) this.decorators.Items).Where<DecoratorRegistration>((Func<DecoratorRegistration, bool>) (d => d.ServiceType == serviceRegistration.ServiceType)).ToList<DecoratorRegistration>();
      list.AddRange(this.GetOpenGenericDecoratorRegistrations(serviceRegistration));
      list.AddRange(this.GetDeferredDecoratorRegistrations(serviceRegistration));
      return list.OrderBy<DecoratorRegistration, int>((Func<DecoratorRegistration, int>) (d => d.Index)).ToArray<DecoratorRegistration>();
    }

    private IEnumerable<DecoratorRegistration> GetOpenGenericDecoratorRegistrations(
      ServiceRegistration serviceRegistration)
    {
      List<DecoratorRegistration> decoratorRegistrations = new List<DecoratorRegistration>();
      TypeInfo typeInfo = serviceRegistration.ServiceType.GetTypeInfo();
      if (typeInfo.IsGenericType)
      {
        Type openGenericServiceType = typeInfo.GetGenericTypeDefinition();
        IEnumerable<DecoratorRegistration> source = ((IEnumerable<DecoratorRegistration>) this.decorators.Items).Where<DecoratorRegistration>((Func<DecoratorRegistration, bool>) (d => d.ServiceType == openGenericServiceType));
        decoratorRegistrations.AddRange(source.Select<DecoratorRegistration, DecoratorRegistration>((Func<DecoratorRegistration, DecoratorRegistration>) (openGenericDecorator => this.CreateClosedGenericDecoratorRegistration(serviceRegistration, openGenericDecorator))).Where<DecoratorRegistration>((Func<DecoratorRegistration, bool>) (dr => dr != null)));
      }
      return (IEnumerable<DecoratorRegistration>) decoratorRegistrations;
    }

    private IEnumerable<DecoratorRegistration> GetDeferredDecoratorRegistrations(
      ServiceRegistration serviceRegistration)
    {
      List<DecoratorRegistration> decoratorRegistrations = new List<DecoratorRegistration>();
      foreach (DecoratorRegistration decoratorRegistration1 in ((IEnumerable<DecoratorRegistration>) this.decorators.Items).Where<DecoratorRegistration>((Func<DecoratorRegistration, bool>) (ds => ds.CanDecorate(serviceRegistration) && ds.HasDeferredImplementingType)))
      {
        DecoratorRegistration decoratorRegistration2 = new DecoratorRegistration();
        decoratorRegistration2.ServiceType = serviceRegistration.ServiceType;
        decoratorRegistration2.ImplementingType = decoratorRegistration1.ImplementingTypeFactory((IServiceFactory) this, serviceRegistration);
        decoratorRegistration2.CanDecorate = (Func<ServiceRegistration, bool>) (sr => true);
        decoratorRegistration2.Index = decoratorRegistration1.Index;
        DecoratorRegistration decoratorRegistration3 = decoratorRegistration2;
        decoratorRegistrations.Add(decoratorRegistration3);
      }
      return (IEnumerable<DecoratorRegistration>) decoratorRegistrations;
    }

    private void EmitNewDecoratorInstance(
      DecoratorRegistration decoratorRegistration,
      IEmitter emitter,
      Action<IEmitter> pushInstance)
    {
      ConstructionInfo constructionInfo = this.GetConstructionInfo((Registration) decoratorRegistration);
      ConstructorDependency representsDecoratorTarget = ServiceContainer.GetConstructorDependencyThatRepresentsDecoratorTarget(decoratorRegistration, constructionInfo);
      if (representsDecoratorTarget != null)
        representsDecoratorTarget.IsDecoratorTarget = true;
      if (constructionInfo.FactoryDelegate != null)
        this.EmitNewDecoratorUsingFactoryDelegate(constructionInfo.FactoryDelegate, emitter, pushInstance);
      else
        this.EmitNewInstanceUsingImplementingType(emitter, constructionInfo, pushInstance);
    }

    private void EmitNewDecoratorUsingFactoryDelegate(
      Delegate factoryDelegate,
      IEmitter emitter,
      Action<IEmitter> pushInstance)
    {
      int index1 = this.constants.Add((object) factoryDelegate);
      Type type = factoryDelegate.GetType();
      emitter.PushConstant(index1, type);
      int index2 = this.constants.Add((object) this);
      emitter.PushConstant(index2, typeof (IServiceFactory));
      int scopeManagerIndex = this.CreateScopeManagerIndex();
      emitter.PushConstant(scopeManagerIndex, typeof (IScopeManager));
      emitter.PushArgument(1);
      emitter.Emit(OpCodes.Call, ServiceFactoryLoader.LoadServiceFactoryMethod);
      pushInstance(emitter);
      MethodInfo declaredMethod = type.GetTypeInfo().GetDeclaredMethod("Invoke");
      emitter.Emit(OpCodes.Callvirt, declaredMethod);
    }

    private void EmitNewInstance(ServiceRegistration serviceRegistration, IEmitter emitter)
    {
      if (serviceRegistration.Value != null)
      {
        int index = this.constants.Add(serviceRegistration.Value);
        Type serviceType = serviceRegistration.ServiceType;
        emitter.PushConstant(index, serviceType);
      }
      else
      {
        ConstructionInfo constructionInfo = this.GetConstructionInfo((Registration) serviceRegistration);
        if (serviceRegistration.FactoryExpression != null)
          this.EmitNewInstanceUsingFactoryDelegate(serviceRegistration, emitter);
        else
          this.EmitNewInstanceUsingImplementingType(emitter, constructionInfo, (Action<IEmitter>) null);
      }
    }

    private void EmitDecorators(
      ServiceRegistration serviceRegistration,
      IEnumerable<DecoratorRegistration> serviceDecorators,
      IEmitter emitter,
      Action<IEmitter> decoratorTargetEmitMethod)
    {
      foreach (DecoratorRegistration serviceDecorator in serviceDecorators)
      {
        if (serviceDecorator.CanDecorate(serviceRegistration))
        {
          Action<IEmitter> currentDecoratorTargetEmitter = decoratorTargetEmitMethod;
          DecoratorRegistration currentDecorator = serviceDecorator;
          decoratorTargetEmitMethod = (Action<IEmitter>) (e => this.EmitNewDecoratorInstance(currentDecorator, e, currentDecoratorTargetEmitter));
        }
      }
      decoratorTargetEmitMethod(emitter);
    }

    private void EmitNewInstanceUsingImplementingType(
      IEmitter emitter,
      ConstructionInfo constructionInfo,
      Action<IEmitter> decoratorTargetEmitMethod)
    {
      this.EmitConstructorDependencies(constructionInfo, emitter, decoratorTargetEmitMethod);
      emitter.Emit(OpCodes.Newobj, constructionInfo.Constructor);
      this.EmitPropertyDependencies(constructionInfo, emitter);
    }

    private void EmitNewInstanceUsingFactoryDelegate(
      ServiceRegistration serviceRegistration,
      IEmitter emitter)
    {
      int index1 = this.constants.Add((object) serviceRegistration.FactoryExpression);
      Type type = serviceRegistration.FactoryExpression.GetType();
      MethodInfo declaredMethod = type.GetTypeInfo().GetDeclaredMethod("Invoke");
      emitter.PushConstant(index1, type);
      ParameterInfo[] parameters = declaredMethod.GetParameters();
      if (parameters.Length == 1 && parameters[0].ParameterType == typeof (ServiceRequest))
      {
        MethodInfo methodInfo = ServiceRequestHelper.CreateServiceRequestMethod.MakeGenericMethod(serviceRegistration.ServiceType);
        emitter.Emit(OpCodes.Ldstr, serviceRegistration.ServiceName);
        int index2 = this.constants.Add((object) this);
        emitter.PushConstant(index2, typeof (IServiceFactory));
        int scopeManagerIndex = this.CreateScopeManagerIndex();
        emitter.PushConstant(scopeManagerIndex, typeof (IScopeManager));
        emitter.PushArgument(1);
        emitter.Emit(OpCodes.Call, ServiceFactoryLoader.LoadServiceFactoryMethod);
        emitter.Emit(OpCodes.Call, methodInfo);
        emitter.Call(declaredMethod);
        emitter.UnboxOrCast(serviceRegistration.ServiceType);
      }
      else
      {
        int index3 = this.constants.Add((object) this);
        emitter.PushConstant(index3, typeof (IServiceFactory));
        int scopeManagerIndex = this.CreateScopeManagerIndex();
        emitter.PushConstant(scopeManagerIndex, typeof (IScopeManager));
        emitter.PushArgument(1);
        emitter.Emit(OpCodes.Call, ServiceFactoryLoader.LoadServiceFactoryMethod);
        if (parameters.Length > 1)
          emitter.PushArguments(((IEnumerable<ParameterInfo>) parameters).Skip<ParameterInfo>(1).ToArray<ParameterInfo>());
        emitter.Call(declaredMethod);
      }
    }

    private void EmitConstructorDependencies(
      ConstructionInfo constructionInfo,
      IEmitter emitter,
      Action<IEmitter> decoratorTargetEmitter)
    {
      foreach (ConstructorDependency constructorDependency in constructionInfo.ConstructorDependencies)
      {
        if (!constructorDependency.IsDecoratorTarget)
          this.EmitConstructorDependency(emitter, (Dependency) constructorDependency);
        else if (constructorDependency.ServiceType.IsLazy())
        {
          LocalBuilder localBuilder = emitter.DeclareLocal(typeof (Scope));
          emitter.PushArgument(1);
          int scopeManagerIndex = this.CreateScopeManagerIndex();
          emitter.PushConstant(scopeManagerIndex, typeof (IScopeManager));
          emitter.Emit(OpCodes.Call, ScopeLoader.GetThisOrCurrentScopeMethod);
          emitter.Store(localBuilder);
          int instanceDelegateIndex = this.CreateInstanceDelegateIndex(decoratorTargetEmitter);
          emitter.PushConstant(instanceDelegateIndex, typeof (GetInstanceDelegate));
          emitter.PushArgument(0);
          emitter.Push(localBuilder);
          MethodInfo methodInfo = LazyHelper.CreateScopedLazyFromDelegateMethod.MakeGenericMethod(((IEnumerable<Type>) constructorDependency.ServiceType.GetTypeInfo().GenericTypeArguments).Last<Type>());
          emitter.Emit(OpCodes.Call, methodInfo);
        }
        else
          decoratorTargetEmitter(emitter);
      }
    }

    private void EmitConstructorDependency(IEmitter emitter, Dependency dependency)
    {
      Action<IEmitter> methodForDependency = this.GetEmitMethodForDependency(dependency);
      try
      {
        methodForDependency(emitter);
        emitter.UnboxOrCast(dependency.ServiceType);
      }
      catch (InvalidOperationException ex)
      {
        throw new InvalidOperationException(string.Format("Unresolved dependency {0}", (object) dependency), (Exception) ex);
      }
    }

    private void EmitPropertyDependency(
      IEmitter emitter,
      PropertyDependency propertyDependency,
      LocalBuilder instanceVariable)
    {
      Action<IEmitter> methodForDependency = this.GetEmitMethodForDependency((Dependency) propertyDependency);
      if (methodForDependency == null)
        return;
      emitter.Push(instanceVariable);
      methodForDependency(emitter);
      emitter.UnboxOrCast(propertyDependency.ServiceType);
      emitter.Call(propertyDependency.Property.SetMethod);
    }

    private Action<IEmitter> GetEmitMethodForDependency(Dependency dependency)
    {
      if (dependency.FactoryExpression != null)
        return (Action<IEmitter>) (skeleton => this.EmitDependencyUsingFactoryExpression(skeleton, dependency));
      Action<IEmitter> methodForDependency1 = (Action<IEmitter>) null;
      string key = string.IsNullOrWhiteSpace(dependency.ServiceName) ? dependency.Name : dependency.ServiceName;
      ThreadSafeDictionary<string, Action<IEmitter>> emitMethods = this.GetEmitMethods(dependency.ServiceType);
      if (emitMethods.Count > 1 && emitMethods.TryGetValue(key, out methodForDependency1))
        return methodForDependency1;
      Action<IEmitter> methodForDependency2 = this.GetEmitMethod(dependency.ServiceType, dependency.ServiceName);
      if (methodForDependency2 == null)
      {
        methodForDependency2 = this.GetEmitMethod(dependency.ServiceType, dependency.Name);
        if (methodForDependency2 == null && dependency.IsRequired)
        {
          if (!(dependency is ConstructorDependency constructorDependency) || !constructorDependency.Parameter.HasDefaultValue || !this.options.EnableOptionalArguments)
            throw new InvalidOperationException(string.Format("Unresolved dependency {0}", (object) dependency));
          methodForDependency2 = this.GetEmitMethodForDefaultValue(constructorDependency);
        }
      }
      return methodForDependency2;
    }

    private Action<IEmitter> GetEmitMethodForDefaultValue(
      ConstructorDependency constructorDependency)
    {
      Type parameterType = constructorDependency.Parameter.ParameterType;
      return (Action<IEmitter>) (emitter =>
      {
        object obj = constructorDependency.Parameter.DefaultValue ?? TypeHelper.GetDefaultValue(parameterType);
        emitter.PushConstantValue(obj, parameterType);
      });
    }

    private void EmitDependencyUsingFactoryExpression(IEmitter emitter, Dependency dependency)
    {
      List<Action<IEmitter>> actionList = new List<Action<IEmitter>>();
      foreach (ParameterInfo parameter in dependency.FactoryExpression.GetMethodInfo().GetParameters())
      {
        if (parameter.ParameterType == typeof (IServiceFactory))
        {
          int serviceFactoryIndex = this.constants.Add((object) this);
          int scopeManagerIndex = this.CreateScopeManagerIndex();
          actionList.Add((Action<IEmitter>) (e => e.PushConstant(serviceFactoryIndex, typeof (IServiceFactory))));
          actionList.Add((Action<IEmitter>) (e => e.PushConstant(scopeManagerIndex, typeof (IScopeManager))));
          actionList.Add((Action<IEmitter>) (e => e.PushArgument(1)));
          actionList.Add((Action<IEmitter>) (e => e.Emit(OpCodes.Call, ServiceFactoryLoader.LoadServiceFactoryMethod)));
        }
        if (parameter.ParameterType == typeof (ParameterInfo))
          actionList.Add((Action<IEmitter>) (e => e.PushConstant(this.constants.Add((object) ((ConstructorDependency) dependency).Parameter), typeof (ParameterInfo))));
        if (parameter.ParameterType == typeof (PropertyInfo))
          actionList.Add((Action<IEmitter>) (e => e.PushConstant(this.constants.Add((object) ((PropertyDependency) dependency).Property), typeof (PropertyInfo))));
        if (parameter.ParameterType == typeof (object[]))
          actionList.Add((Action<IEmitter>) (e => ServiceContainer.PushRuntimeArguments(e)));
      }
      int index = this.constants.Add((object) dependency.FactoryExpression);
      Type type = dependency.FactoryExpression.GetType();
      MethodInfo declaredMethod = type.GetTypeInfo().GetDeclaredMethod("Invoke");
      emitter.PushConstant(index, type);
      foreach (Action<IEmitter> action in actionList)
        action(emitter);
      emitter.Call(declaredMethod);
    }

    private void EmitPropertyDependencies(ConstructionInfo constructionInfo, IEmitter emitter)
    {
      if (constructionInfo.PropertyDependencies.Count == 0)
        return;
      LocalBuilder localBuilder = emitter.DeclareLocal(constructionInfo.ImplementingType);
      emitter.Store(localBuilder);
      foreach (PropertyDependency propertyDependency in constructionInfo.PropertyDependencies)
        this.EmitPropertyDependency(emitter, propertyDependency, localBuilder);
      emitter.Push(localBuilder);
    }

    private Action<IEmitter> CreateEmitMethodForUnknownService(Type serviceType, string serviceName)
    {
      Action<IEmitter> forUnknownService = (Action<IEmitter>) null;
      if (this.CanRedirectRequestForDefaultServiceToSingleNamedService(serviceType, serviceName))
        forUnknownService = this.CreateServiceEmitterBasedOnSingleNamedInstance(serviceType);
      else if (serviceType.IsLazy())
        forUnknownService = this.CreateEmitMethodBasedOnLazyServiceRequest(serviceType);
      else if (serviceType.IsFuncWithParameters())
        forUnknownService = this.CreateEmitMethodBasedParameterizedFuncRequest(serviceType, serviceName);
      else if (serviceType.IsFuncRepresentingService() || serviceType.IsFuncRepresentingNamedService())
        forUnknownService = this.CreateEmitMethodBasedOnFuncServiceRequest(serviceType);
      else if (serviceType.IsEnumerableOfT())
        forUnknownService = this.CreateEmitMethodBasedOnClosedGenericServiceRequest(serviceType, serviceName) ?? this.CreateEmitMethodForEnumerableServiceServiceRequest(serviceType);
      else if (serviceType.IsArray)
        forUnknownService = this.CreateEmitMethodForArrayServiceRequest(serviceType);
      else if (serviceType.IsReadOnlyCollectionOfT() || serviceType.IsReadOnlyListOfT())
        forUnknownService = this.CreateEmitMethodBasedOnClosedGenericServiceRequest(serviceType, serviceName) ?? this.CreateEmitMethodForReadOnlyCollectionServiceRequest(serviceType);
      else if (serviceType.IsListOfT())
        forUnknownService = this.CreateEmitMethodBasedOnClosedGenericServiceRequest(serviceType, serviceName) ?? this.CreateEmitMethodForListServiceRequest(serviceType);
      else if (serviceType.IsCollectionOfT())
        forUnknownService = this.CreateEmitMethodBasedOnClosedGenericServiceRequest(serviceType, serviceName) ?? this.CreateEmitMethodForListServiceRequest(serviceType);
      else if (serviceType.IsClosedGeneric())
        forUnknownService = this.CreateEmitMethodBasedOnClosedGenericServiceRequest(serviceType, serviceName);
      return forUnknownService;
    }

    private Action<IEmitter> CreateEmitMethodBasedOnFuncServiceRequest(Type serviceType)
    {
      Type type = ((IEnumerable<Type>) serviceType.GetTypeInfo().GenericTypeArguments).Last<Type>();
      if (serviceType.IsFuncRepresentingService())
      {
        MethodInfo createScopedGenericFuncMethod = FuncHelper.CreateScopedGenericFuncMethod.MakeGenericMethod(type);
        return (Action<IEmitter>) (e =>
        {
          e.PushConstant(this.constants.Add((object) this), typeof (ServiceContainer));
          int scopeManagerIndex = this.CreateScopeManagerIndex();
          e.PushArgument(1);
          e.PushConstant(scopeManagerIndex, typeof (IScopeManager));
          e.Emit(OpCodes.Call, ScopeLoader.GetThisOrCurrentScopeMethod);
          e.Emit(OpCodes.Call, createScopedGenericFuncMethod);
        });
      }
      MethodInfo createScopedGenericNamedFuncMethod = FuncHelper.CreateScopedGenericNamedFuncMethod.MakeGenericMethod(type);
      return (Action<IEmitter>) (e =>
      {
        e.PushConstant(this.constants.Add((object) this), typeof (ServiceContainer));
        int scopeManagerIndex = this.CreateScopeManagerIndex();
        e.PushArgument(1);
        e.PushConstant(scopeManagerIndex, typeof (IScopeManager));
        e.Emit(OpCodes.Call, ScopeLoader.GetThisOrCurrentScopeMethod);
        e.Emit(OpCodes.Call, createScopedGenericNamedFuncMethod);
      });
    }

    private Action<IEmitter> CreateEmitMethodBasedParameterizedFuncRequest(
      Type serviceType,
      string serviceName)
    {
      int constantIndex = this.constants.Add((object) (!string.IsNullOrEmpty(serviceName) ? ReflectionHelper.CreateGetNamedInstanceWithParametersDelegate((IServiceFactory) this, serviceType, serviceName) : this.CreateGetInstanceWithParametersDelegate(serviceType)));
      return (Action<IEmitter>) (e => e.PushConstant(constantIndex, serviceType));
    }

    private Delegate CreateGetInstanceWithParametersDelegate(Type serviceType)
    {
      return ReflectionHelper.GetGetInstanceWithParametersMethod(serviceType).CreateDelegate(serviceType, (object) this);
    }

    private Action<IEmitter> CreateServiceEmitterBasedOnFactoryRule(
      ServiceContainer.FactoryRule rule,
      Type serviceType,
      string serviceName)
    {
      ServiceRegistration serviceRegistration1 = new ServiceRegistration();
      serviceRegistration1.ServiceType = serviceType;
      serviceRegistration1.ServiceName = serviceName;
      serviceRegistration1.FactoryExpression = (Delegate) rule.Factory;
      serviceRegistration1.Lifetime = ServiceContainer.CloneLifeTime(rule.LifeTime) ?? this.DefaultLifetime;
      ServiceRegistration serviceRegistration = serviceRegistration1;
      return rule.LifeTime != null ? (Action<IEmitter>) (emitter => this.EmitLifetime(serviceRegistration, (Action<IEmitter>) (e => this.EmitNewInstanceWithDecorators(serviceRegistration, e)), emitter)) : (Action<IEmitter>) (emitter => this.EmitNewInstanceWithDecorators(serviceRegistration, emitter));
    }

    private Action<IEmitter> CreateEmitMethodForArrayServiceRequest(Type serviceType)
    {
      return this.CreateEmitMethodForEnumerableServiceServiceRequest(serviceType);
    }

    private Action<IEmitter> CreateEmitMethodForListServiceRequest(Type serviceType)
    {
      Action<IEmitter> enumerableEmitter = this.CreateEmitMethodForEnumerableServiceServiceRequest(serviceType);
      MethodInfo closedGenericToListMethod = typeof (Enumerable).GetTypeInfo().GetDeclaredMethod("ToList").MakeGenericMethod(TypeHelper.GetElementType(serviceType));
      return (Action<IEmitter>) (ms =>
      {
        enumerableEmitter(ms);
        ms.Emit(OpCodes.Call, closedGenericToListMethod);
      });
    }

    private Action<IEmitter> CreateEmitMethodForReadOnlyCollectionServiceRequest(Type serviceType)
    {
      ConstructorInfo constructorInfo = typeof (ReadOnlyCollection<>).MakeGenericType(TypeHelper.GetElementType(serviceType)).GetTypeInfo().DeclaredConstructors.Single<ConstructorInfo>();
      Action<IEmitter> listEmitMethod = this.CreateEmitMethodForListServiceRequest(serviceType);
      return (Action<IEmitter>) (emitter =>
      {
        listEmitMethod(emitter);
        emitter.New(constructorInfo);
      });
    }

    private Action<IEmitter> CreateEmitMethodBasedOnLazyServiceRequest(Type serviceType)
    {
      Type type = ((IEnumerable<Type>) serviceType.GetTypeInfo().GenericTypeArguments).Last<Type>();
      MethodInfo createScopedLazyMethod = LazyHelper.CreateScopedLazyMethod.MakeGenericMethod(type);
      return (Action<IEmitter>) (e =>
      {
        e.PushConstant(this.constants.Add((object) this), typeof (ServiceContainer));
        int scopeManagerIndex = this.CreateScopeManagerIndex();
        e.PushArgument(1);
        e.PushConstant(scopeManagerIndex, typeof (IScopeManager));
        e.Emit(OpCodes.Call, ScopeLoader.GetThisOrCurrentScopeMethod);
        e.Emit(OpCodes.Call, createScopedLazyMethod);
      });
    }

    private ThreadSafeDictionary<string, ServiceRegistration> GetOpenGenericServiceRegistrations(
      Type openGenericServiceType)
    {
      return this.GetAvailableServices(openGenericServiceType);
    }

    private Action<IEmitter> CreateEmitMethodBasedOnClosedGenericServiceRequest(
      Type closedGenericServiceType,
      string serviceName)
    {
      ThreadSafeDictionary<string, ServiceRegistration> serviceRegistrations = this.GetOpenGenericServiceRegistrations(closedGenericServiceType.GetGenericTypeDefinition());
      Dictionary<string, ServiceContainer.ClosedGenericCandidate> source = new Dictionary<string, ServiceContainer.ClosedGenericCandidate>((IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase);
      foreach (ServiceRegistration serviceRegistration in (IEnumerable<ServiceRegistration>) serviceRegistrations.Values)
      {
        Type type = this.GenericArgumentMapper.TryMakeGenericType(closedGenericServiceType, serviceRegistration.ImplementingType);
        if (type != (Type) null && closedGenericServiceType.IsAssignableFrom(type))
          source.Add(serviceRegistration.ServiceName, new ServiceContainer.ClosedGenericCandidate(type, serviceRegistration.Lifetime));
      }
      ServiceContainer.ClosedGenericCandidate candidate;
      if (string.IsNullOrWhiteSpace(serviceName))
      {
        string key = string.Empty;
        if (source.Count > 0)
          key = this.options.DefaultServiceSelector(source.Keys.OrderBy<string, string>((Func<string, string>) (k => k)).ToArray<string>());
        if (source.TryGetValue(key, out candidate))
          return RegisterAndGetEmitMethod();
        if (source.Count != 1)
          return (Action<IEmitter>) null;
        candidate = source.First<KeyValuePair<string, ServiceContainer.ClosedGenericCandidate>>().Value;
        return RegisterAndGetEmitMethod();
      }
      return source.TryGetValue(serviceName, out candidate) ? RegisterAndGetEmitMethod() : (Action<IEmitter>) null;

      Action<IEmitter> RegisterAndGetEmitMethod()
      {
        ServiceRegistration serviceRegistration1 = new ServiceRegistration();
        serviceRegistration1.ServiceType = closedGenericServiceType;
        serviceRegistration1.ImplementingType = candidate.ClosedGenericImplementingType;
        serviceRegistration1.ServiceName = serviceName;
        serviceRegistration1.Lifetime = ServiceContainer.CloneLifeTime(candidate.Lifetime) ?? this.DefaultLifetime;
        ServiceRegistration serviceRegistration2 = serviceRegistration1;
        this.Register(serviceRegistration2);
        return this.GetEmitMethod(serviceRegistration2.ServiceType, serviceRegistration2.ServiceName);
      }
    }

    private Action<IEmitter> CreateEmitMethodForEnumerableServiceServiceRequest(Type serviceType)
    {
      Type actualServiceType = TypeHelper.GetElementType(serviceType);
      if (actualServiceType.GetTypeInfo().IsGenericType)
      {
        foreach (var data in this.GetOpenGenericServiceRegistrations(actualServiceType.GetGenericTypeDefinition()).Values.Select(r => new
        {
          Lifetime = r.Lifetime,
          ServiceName = r.ServiceName,
          closedGenericImplementingType = this.GenericArgumentMapper.TryMakeGenericType(actualServiceType, r.ImplementingType)
        }).Where(t => t.closedGenericImplementingType != (Type) null))
        {
          ServiceRegistration serviceRegistration = new ServiceRegistration();
          serviceRegistration.ServiceType = actualServiceType;
          serviceRegistration.ImplementingType = data.closedGenericImplementingType;
          serviceRegistration.ServiceName = data.ServiceName;
          serviceRegistration.Lifetime = ServiceContainer.CloneLifeTime(data.Lifetime) ?? this.DefaultLifetime;
          this.Register(serviceRegistration);
        }
      }
      List<Action<IEmitter>> emitMethods = (!this.options.EnableVariance ? 0 : (this.options.VarianceFilter(serviceType) ? 1 : 0)) == 0 ? this.GetEmitMethods(actualServiceType).OrderBy<KeyValuePair<string, Action<IEmitter>>, string>((Func<KeyValuePair<string, Action<IEmitter>>, string>) (kv => kv.Key)).Select<KeyValuePair<string, Action<IEmitter>>, Action<IEmitter>>((Func<KeyValuePair<string, Action<IEmitter>>, Action<IEmitter>>) (kv => kv.Value)).ToList<Action<IEmitter>>() : this.emitters.Where<KeyValuePair<Type, ThreadSafeDictionary<string, Action<IEmitter>>>>((Func<KeyValuePair<Type, ThreadSafeDictionary<string, Action<IEmitter>>>, bool>) (kv => actualServiceType.GetTypeInfo().IsAssignableFrom(kv.Key.GetTypeInfo()))).SelectMany<KeyValuePair<Type, ThreadSafeDictionary<string, Action<IEmitter>>>, KeyValuePair<string, Action<IEmitter>>>((Func<KeyValuePair<Type, ThreadSafeDictionary<string, Action<IEmitter>>>, IEnumerable<KeyValuePair<string, Action<IEmitter>>>>) (kv => (IEnumerable<KeyValuePair<string, Action<IEmitter>>>) kv.Value)).OrderBy<KeyValuePair<string, Action<IEmitter>>, string>((Func<KeyValuePair<string, Action<IEmitter>>, string>) (kv => kv.Key)).Select<KeyValuePair<string, Action<IEmitter>>, Action<IEmitter>>((Func<KeyValuePair<string, Action<IEmitter>>, Action<IEmitter>>) (kv => kv.Value)).ToList<Action<IEmitter>>();
      if (this.dependencyStack.Count > 0 && emitMethods.Contains(this.dependencyStack.Peek()))
        emitMethods.Remove(this.dependencyStack.Peek());
      return (Action<IEmitter>) (e => ServiceContainer.EmitEnumerable((IList<Action<IEmitter>>) emitMethods, actualServiceType, e));
    }

    private Action<IEmitter> CreateServiceEmitterBasedOnSingleNamedInstance(Type serviceType)
    {
      return this.GetEmitMethod(serviceType, this.GetEmitMethods(serviceType).First<KeyValuePair<string, Action<IEmitter>>>().Key);
    }

    private bool CanRedirectRequestForDefaultServiceToSingleNamedService(
      Type serviceType,
      string serviceName)
    {
      return string.IsNullOrEmpty(serviceName) && this.GetEmitMethods(serviceType).Count == 1;
    }

    private ConstructionInfo GetConstructionInfo(Registration registration)
    {
      return this.constructionInfoProvider.Value.GetConstructionInfo(registration);
    }

    private ThreadSafeDictionary<string, Action<IEmitter>> GetEmitMethods(Type serviceType)
    {
      return this.emitters.GetOrAdd(serviceType, (Func<Type, ThreadSafeDictionary<string, Action<IEmitter>>>) (s => new ThreadSafeDictionary<string, Action<IEmitter>>((IEqualityComparer<string>) StringComparer.CurrentCultureIgnoreCase)));
    }

    private ThreadSafeDictionary<string, ServiceRegistration> GetAvailableServices(Type serviceType)
    {
      return this.availableServices.GetOrAdd(serviceType, (Func<Type, ThreadSafeDictionary<string, ServiceRegistration>>) (s => new ThreadSafeDictionary<string, ServiceRegistration>((IEqualityComparer<string>) StringComparer.CurrentCultureIgnoreCase)));
    }

    private ThreadSafeDictionary<string, Delegate> GetConstructorDependencyFactories(
      Type dependencyType)
    {
      return this.constructorDependencyFactories.GetOrAdd(dependencyType, (Func<Type, ThreadSafeDictionary<string, Delegate>>) (d => new ThreadSafeDictionary<string, Delegate>((IEqualityComparer<string>) StringComparer.CurrentCultureIgnoreCase)));
    }

    private ThreadSafeDictionary<string, Delegate> GetPropertyDependencyFactories(
      Type dependencyType)
    {
      return this.propertyDependencyFactories.GetOrAdd(dependencyType, (Func<Type, ThreadSafeDictionary<string, Delegate>>) (d => new ThreadSafeDictionary<string, Delegate>((IEqualityComparer<string>) StringComparer.CurrentCultureIgnoreCase)));
    }

    private void RegisterService(
      Type serviceType,
      Type implementingType,
      ILifetime lifetime,
      string serviceName)
    {
      Ensure.IsNotNull<Type>(serviceType, "type");
      Ensure.IsNotNull<Type>(implementingType, nameof (implementingType));
      Ensure.IsNotNull<string>(serviceName, nameof (serviceName));
      this.EnsureConstructable(serviceType, implementingType);
      ServiceRegistration serviceRegistration = new ServiceRegistration();
      serviceRegistration.ServiceType = serviceType;
      serviceRegistration.ImplementingType = implementingType;
      serviceRegistration.ServiceName = serviceName;
      serviceRegistration.Lifetime = lifetime ?? this.DefaultLifetime;
      this.Register(serviceRegistration);
    }

    private void EnsureConstructable(Type serviceType, Type implementingType)
    {
      if (implementingType.GetTypeInfo().ContainsGenericParameters)
      {
        try
        {
          this.GenericArgumentMapper.Map(serviceType, implementingType).GetMappedArguments();
        }
        catch (InvalidOperationException ex)
        {
          throw new ArgumentOutOfRangeException(nameof (implementingType), ex.Message);
        }
      }
      else if (!serviceType.GetTypeInfo().IsAssignableFrom(implementingType.GetTypeInfo()))
        throw new ArgumentOutOfRangeException(nameof (implementingType), "The implementing type " + implementingType.FullName + " is not assignable from " + serviceType.FullName + ".");
    }

    private Action<IEmitter> ResolveEmitMethod(ServiceRegistration serviceRegistration)
    {
      return (Action<IEmitter>) (emitter =>
      {
        foreach (ServiceContainer.ServiceOverride serviceOverride in ((IEnumerable<ServiceContainer.ServiceOverride>) this.overrides.Items).Where<ServiceContainer.ServiceOverride>((Func<ServiceContainer.ServiceOverride, bool>) (so => so.CanOverride(serviceRegistration))).ToArray<ServiceContainer.ServiceOverride>())
          serviceRegistration = serviceOverride.Execute((IServiceFactory) this, serviceRegistration);
        if (serviceRegistration.Lifetime == null)
        {
          if (this.options.OptimizeForLargeObjectGraphs)
            this.EmitLifetime(serviceRegistration, (Action<IEmitter>) (e => this.EmitNewInstanceWithDecorators(serviceRegistration, e)), emitter);
          else
            this.EmitNewInstanceWithDecorators(serviceRegistration, emitter);
        }
        else
          this.EmitLifetime(serviceRegistration, (Action<IEmitter>) (e => this.EmitNewInstanceWithDecorators(serviceRegistration, e)), emitter);
      });
    }

    private void EmitNewInstanceWithDecorators(
      ServiceRegistration serviceRegistration,
      IEmitter emitter)
    {
      DecoratorRegistration[] decorators = this.GetDecorators(serviceRegistration);
      if (decorators.Length != 0)
        this.EmitDecorators(serviceRegistration, (IEnumerable<DecoratorRegistration>) decorators, emitter, (Action<IEmitter>) (dm => this.EmitNewInstance(serviceRegistration, dm)));
      else
        this.EmitNewInstance(serviceRegistration, emitter);
      if (serviceRegistration.Lifetime is PerContainerLifetime && IsNotServiceFactory(serviceRegistration.ServiceType))
      {
        MethodInfo methodInfo = ServiceContainer.OpenGenericTrackInstanceMethod.MakeGenericMethod(emitter.StackType);
        int index = this.constants.Add((object) this);
        emitter.PushConstant(index, typeof (ServiceContainer));
        emitter.Emit(OpCodes.Call, methodInfo);
      }
      ServiceContainer.Initializer[] array = ((IEnumerable<ServiceContainer.Initializer>) this.initializers.Items).Where<ServiceContainer.Initializer>((Func<ServiceContainer.Initializer, bool>) (i => i.Predicate(serviceRegistration))).ToArray<ServiceContainer.Initializer>();
      if (array.Length == 0)
        return;
      LocalBuilder localBuilder = emitter.DeclareLocal(serviceRegistration.ServiceType);
      emitter.Store(localBuilder);
      foreach (ServiceContainer.Initializer initializer in array)
      {
        Type type = initializer.Initialize.GetType();
        int index1 = this.constants.Add((object) initializer.Initialize);
        emitter.PushConstant(index1, type);
        int index2 = this.constants.Add((object) this);
        emitter.PushConstant(index2, typeof (IServiceFactory));
        int scopeManagerIndex = this.CreateScopeManagerIndex();
        emitter.PushConstant(scopeManagerIndex, typeof (IScopeManager));
        emitter.PushArgument(1);
        emitter.Emit(OpCodes.Call, ServiceFactoryLoader.LoadServiceFactoryMethod);
        emitter.Push(localBuilder);
        MethodInfo declaredMethod = type.GetTypeInfo().GetDeclaredMethod("Invoke");
        emitter.Call(declaredMethod);
      }
      emitter.Push(localBuilder);

      static bool IsNotServiceFactory(Type serviceType)
      {
        return !typeof (IServiceFactory).GetTypeInfo().IsAssignableFrom(serviceType.GetTypeInfo());
      }
    }

    private int GetInstanceDelegateIndex(
      ServiceRegistration serviceRegistration,
      Action<IEmitter> emitMethod)
    {
      if (this.servicesToDelegatesIndex.ContainsUninitializedValue(serviceRegistration))
        throw new InvalidOperationException(string.Format("Recursive dependency detected: ServiceType:{0}, ServiceName:{1}]", (object) serviceRegistration.ServiceType, (object) serviceRegistration.ServiceName));
      return this.servicesToDelegatesIndex.GetOrAdd(serviceRegistration, (Func<ServiceRegistration, int>) (_ => this.CreateInstanceDelegateIndex(emitMethod)));
    }

    private void EmitLifetime(
      ServiceRegistration serviceRegistration,
      Action<IEmitter> emitMethod,
      IEmitter emitter)
    {
      if (serviceRegistration.Lifetime == null)
      {
        int instanceDelegateIndex = this.GetInstanceDelegateIndex(serviceRegistration, emitMethod);
        MethodInfo declaredMethod = typeof (GetInstanceDelegate).GetTypeInfo().GetDeclaredMethod("Invoke");
        emitter.PushConstant(instanceDelegateIndex, typeof (GetInstanceDelegate));
        emitter.PushArgument(0);
        this.PushScope(emitter);
        emitter.Emit(OpCodes.Callvirt, declaredMethod);
      }
      else
      {
        if (serviceRegistration.Lifetime is PerScopeLifetime)
        {
          int orAdd = this.servicesToDelegatesIndex.GetOrAdd(serviceRegistration, (Func<ServiceRegistration, int>) (_ => this.CreateInstanceDelegateIndex(emitMethod)));
          this.PushScope(emitter);
          emitter.Emit(OpCodes.Call, ScopeLoader.ValidateScopeMethod.MakeGenericMethod(serviceRegistration.ServiceType.UnderlyingSystemType));
          emitter.PushConstant(orAdd, typeof (GetInstanceDelegate));
          emitter.PushArgument(0);
          emitter.Push(orAdd);
          emitter.Call(ScopeLoader.GetScopedInstanceMethod);
        }
        else if (serviceRegistration.Lifetime is PerRequestLifeTime)
        {
          LocalBuilder localBuilder = emitter.DeclareLocal(typeof (Scope));
          int orAdd = this.servicesToDelegatesIndex.GetOrAdd(serviceRegistration, (Func<ServiceRegistration, int>) (_ => this.CreateInstanceDelegateIndex(emitMethod)));
          MethodInfo declaredMethod = typeof (GetInstanceDelegate).GetTypeInfo().GetDeclaredMethod("Invoke");
          emitter.PushConstant(orAdd, typeof (GetInstanceDelegate));
          emitter.PushArgument(0);
          this.PushScope(emitter);
          emitter.Store(localBuilder);
          emitter.Push(localBuilder);
          emitter.Emit(OpCodes.Callvirt, declaredMethod);
          emitter.Push(localBuilder);
          emitter.Emit(OpCodes.Call, ScopeLoader.ValidateTrackedTransientMethod);
        }
        else
        {
          MethodInfo getInstanceMethod = LifetimeHelper.GetNonClosingGetInstanceMethod(serviceRegistration.Lifetime.GetType());
          if (getInstanceMethod != (MethodInfo) null)
          {
            int orAdd = this.servicesToDelegatesIndex.GetOrAdd(serviceRegistration, (Func<ServiceRegistration, int>) (_ => this.CreateInstanceDelegateIndex(emitMethod)));
            int lifetimeIndex = this.CreateLifetimeIndex(serviceRegistration.Lifetime);
            emitter.PushConstant(lifetimeIndex, serviceRegistration.Lifetime.GetType());
            emitter.PushConstant(orAdd, typeof (GetInstanceDelegate));
            this.PushScope(emitter);
            emitter.PushArgument(0);
            emitter.Call(getInstanceMethod);
          }
          else
          {
            int orAdd = this.servicesToDelegatesIndex.GetOrAdd(serviceRegistration, (Func<ServiceRegistration, int>) (_ => this.CreateInstanceDelegateIndex(emitMethod)));
            int lifetimeIndex = this.CreateLifetimeIndex(serviceRegistration.Lifetime);
            LocalBuilder localBuilder = emitter.DeclareLocal(typeof (Scope));
            this.PushScope(emitter);
            emitter.Store(localBuilder);
            emitter.PushConstant(lifetimeIndex, typeof (ILifetime));
            emitter.PushConstant(orAdd, typeof (GetInstanceDelegate));
            emitter.PushArgument(0);
            emitter.Push(localBuilder);
            emitter.Emit(OpCodes.Call, FuncHelper.CreateScopedFuncMethod);
            emitter.Push(localBuilder);
            emitter.Call(LifetimeHelper.GetInstanceMethod);
          }
        }
        if (IsNotServiceFactory(serviceRegistration.ServiceType) && !(serviceRegistration.Lifetime is PerContainerLifetime))
          this.disposableLifeTimes.Add(serviceRegistration.Lifetime);
      }

      static bool IsNotServiceFactory(Type serviceType)
      {
        return !typeof (IServiceFactory).GetTypeInfo().IsAssignableFrom(serviceType.GetTypeInfo());
      }
    }

    private void PushScope(IEmitter emitter)
    {
      if (this.options.EnableCurrentScope)
      {
        int scopeManagerIndex = this.CreateScopeManagerIndex();
        emitter.PushArgument(1);
        emitter.PushConstant(scopeManagerIndex, typeof (IScopeManager));
        emitter.Emit(OpCodes.Call, ScopeLoader.GetThisOrCurrentScopeMethod);
      }
      else
        emitter.PushArgument(1);
    }

    private int CreateScopeManagerIndex()
    {
      return this.constants.Add((object) this.ScopeManagerProvider.GetScopeManager((IServiceFactory) this));
    }

    private int CreateInstanceDelegateIndex(Action<IEmitter> emitMethod)
    {
      return this.constants.Add((object) this.CreateDynamicMethodDelegate(emitMethod));
    }

    private int CreateLifetimeIndex(ILifetime lifetime) => this.constants.Add((object) lifetime);

    private GetInstanceDelegate CreateDefaultDelegate(Type serviceType, bool throwError)
    {
      this.log.Info(string.Format("Compiling delegate for resolving service : {0}", (object) serviceType));
      GetInstanceDelegate defaultDelegate = this.CreateDelegate(serviceType, string.Empty, throwError);
      if (defaultDelegate == null)
        return (GetInstanceDelegate) ((args, scope) => (object) null);
      Interlocked.Exchange<ImmutableHashTable<Type, GetInstanceDelegate>>(ref this.delegates, this.delegates.Add<Type, GetInstanceDelegate>(serviceType, defaultDelegate));
      return defaultDelegate;
    }

    private GetInstanceDelegate CreateNamedDelegate((Type, string) key, bool throwError)
    {
      this.log.Info(string.Format("Compiling delegate for resolving service : {0}, name: {1}", (object) key.Item1, (object) key.Item2));
      GetInstanceDelegate namedDelegate = this.CreateDelegate(key.Item1, key.Item2, throwError);
      if (namedDelegate == null)
        return (GetInstanceDelegate) ((args, scope) => (object) null);
      Interlocked.Exchange<ImmutableHashTable<(Type, string), GetInstanceDelegate>>(ref this.namedDelegates, this.namedDelegates.Add<(Type, string), GetInstanceDelegate>(key, namedDelegate));
      return namedDelegate;
    }

    private GetInstanceDelegate CreateDelegate(
      Type serviceType,
      string serviceName,
      bool throwError)
    {
      lock (this.lockObject)
      {
        Action<IEmitter> emitMethod = this.GetEmitMethod(serviceType, serviceName);
        if (emitMethod == null & throwError)
        {
          LazyConcurrentDictionary<ServiceRegistration, int> toDelegatesIndex = this.servicesToDelegatesIndex;
          ServiceRegistration key = new ServiceRegistration();
          key.ServiceType = serviceType;
          key.ServiceName = serviceName;
          toDelegatesIndex.Remove(key);
          throw new InvalidOperationException(string.Format("Unable to resolve type: {0}, service name: {1}", (object) serviceType, (object) serviceName));
        }
        if (emitMethod == null)
          return (GetInstanceDelegate) null;
        try
        {
          return this.CreateDynamicMethodDelegate(emitMethod);
        }
        catch (InvalidOperationException ex)
        {
          this.dependencyStack.Clear();
          LazyConcurrentDictionary<ServiceRegistration, int> toDelegatesIndex = this.servicesToDelegatesIndex;
          ServiceRegistration key = new ServiceRegistration();
          key.ServiceType = serviceType;
          key.ServiceName = serviceName;
          toDelegatesIndex.Remove(key);
          throw new InvalidOperationException(string.Format("Unable to resolve type: {0}, service name: {1}", (object) serviceType, (object) serviceName), (Exception) ex);
        }
      }
    }

    private void RegisterValue(Type serviceType, object value, string serviceName)
    {
      ServiceRegistration serviceRegistration = new ServiceRegistration();
      serviceRegistration.ServiceType = serviceType;
      serviceRegistration.ServiceName = serviceName;
      serviceRegistration.Value = value;
      serviceRegistration.Lifetime = (ILifetime) new PerContainerLifetime();
      this.Register(serviceRegistration);
    }

    private void RegisterServiceFromLambdaExpression<TService>(
      Delegate factory,
      ILifetime lifetime,
      string serviceName)
    {
      ServiceRegistration serviceRegistration = new ServiceRegistration();
      serviceRegistration.ServiceType = typeof (TService);
      serviceRegistration.FactoryExpression = factory;
      serviceRegistration.ServiceName = serviceName;
      serviceRegistration.Lifetime = lifetime ?? this.DefaultLifetime;
      this.Register(serviceRegistration);
    }

    private struct ClosedGenericCandidate
    {
      public ClosedGenericCandidate(Type closedGenericImplementingType, ILifetime lifetime)
      {
        this.ClosedGenericImplementingType = closedGenericImplementingType;
        this.Lifetime = lifetime;
      }

      public Type ClosedGenericImplementingType { get; }

      public ILifetime Lifetime { get; }
    }

    private class Storage<T>
    {
      public T[] Items = Array.Empty<T>();
      private readonly object lockObject = new object();

      public int Add(T value)
      {
        int num = Array.IndexOf<T>(this.Items, value);
        return num == -1 ? this.TryAddValue(value) : num;
      }

      private int TryAddValue(T value)
      {
        lock (this.lockObject)
        {
          int num = Array.IndexOf<T>(this.Items, value);
          if (num == -1)
            num = this.AddValue(value);
          return num;
        }
      }

      private int AddValue(T value)
      {
        int length = this.Items.Length;
        T[] snapshot = this.CreateSnapshot();
        snapshot[length] = value;
        this.Items = snapshot;
        return length;
      }

      private T[] CreateSnapshot()
      {
        T[] destinationArray = new T[this.Items.Length + 1];
        Array.Copy((Array) this.Items, (Array) destinationArray, this.Items.Length);
        return destinationArray;
      }
    }

    private class PropertyDependencyDisabler : IPropertyDependencySelector
    {
      public IEnumerable<PropertyDependency> Execute(Type type)
      {
        return (IEnumerable<PropertyDependency>) Array.Empty<PropertyDependency>();
      }
    }

    private class DynamicMethodSkeleton : IMethodSkeleton
    {
      private IEmitter emitter;
      private DynamicMethod dynamicMethod;

      public DynamicMethodSkeleton(Type returnType, Type[] parameterTypes)
      {
        this.CreateDynamicMethod(returnType, parameterTypes);
      }

      public IEmitter GetEmitter() => this.emitter;

      public Delegate CreateDelegate(Type delegateType)
      {
        return this.dynamicMethod.CreateDelegate(delegateType);
      }

      private void CreateDynamicMethod(Type returnType, Type[] parameterTypes)
      {
        this.dynamicMethod = new DynamicMethod(returnType, parameterTypes);
        this.emitter = (IEmitter) new Emitter(this.dynamicMethod.GetILGenerator(), parameterTypes);
      }
    }

    private class ServiceRegistry<T> : ThreadSafeDictionary<Type, ThreadSafeDictionary<string, T>>
    {
    }

    private class FactoryRule
    {
      public Func<Type, string, bool> CanCreateInstance { get; set; }

      public Func<ServiceRequest, object> Factory { get; set; }

      public ILifetime LifeTime { get; set; }
    }

    private class Initializer
    {
      public Func<ServiceRegistration, bool> Predicate { get; set; }

      public Action<IServiceFactory, object> Initialize { get; set; }
    }

    private class ServiceOverride
    {
      private readonly object lockObject = new object();
      private readonly Func<IServiceFactory, ServiceRegistration, ServiceRegistration> serviceRegistrationFactory;
      private bool hasExecuted;

      public ServiceOverride(
        Func<ServiceRegistration, bool> canOverride,
        Func<IServiceFactory, ServiceRegistration, ServiceRegistration> serviceRegistrationFactory)
      {
        this.CanOverride = canOverride;
        this.serviceRegistrationFactory = serviceRegistrationFactory;
      }

      public Func<ServiceRegistration, bool> CanOverride { get; }

      [ExcludeFromCodeCoverage]
      public ServiceRegistration Execute(
        IServiceFactory serviceFactory,
        ServiceRegistration serviceRegistration)
      {
        if (this.hasExecuted)
          return serviceRegistration;
        lock (this.lockObject)
        {
          if (this.hasExecuted)
            return serviceRegistration;
          this.hasExecuted = true;
          return this.serviceRegistrationFactory(serviceFactory, serviceRegistration);
        }
      }
    }
  }
}
